Skip to content

Automatically wrapping with Clang.jl#149

Closed
jkozdon wants to merge 83 commits into
mainfrom
jek/gen
Closed

Automatically wrapping with Clang.jl#149
jkozdon wants to merge 83 commits into
mainfrom
jek/gen

Conversation

@jkozdon
Copy link
Copy Markdown
Member

@jkozdon jkozdon commented Jul 15, 2021

Experimenting to play with #147

Todo

@jkozdon
Copy link
Copy Markdown
Member Author

jkozdon commented Jul 15, 2021

Doesn't work with everything yet but you can call initialize and finalize.

@jkozdon
Copy link
Copy Markdown
Member Author

jkozdon commented Jul 15, 2021

Input:

# For some reason you need to initialize MPI before using multiple libraries.
# Need to debug this
using MPI
MPI.Initialized() || MPI.Init()
using PETSc
for petsclib in PETSc.LibPETSc.petsclibs
    println(splitpath(petsclib.petsc_library)[end])
    @show PETSc.initialized(petsclib)
    @show PETSc.initialize(petsclib)
    @show PETSc.initialized(petsclib)
    @show PETSc.finalized(petsclib)
    @show PETSc.finalize(petsclib)
    @show PETSc.initialized(petsclib)
    @show PETSc.finalized(petsclib)
    println()
end

Output:

libpetsc_double_real_Int64.dylib
PETSc.initialized(petsclib) = false
PETSc.initialize(petsclib) = nothing
PETSc.initialized(petsclib) = true
PETSc.finalized(petsclib) = false
PETSc.finalize(petsclib) = nothing
PETSc.initialized(petsclib) = false
PETSc.finalized(petsclib) = true

libpetsc_single_real_Int64.dylib
PETSc.initialized(petsclib) = false
PETSc.initialize(petsclib) = nothing
PETSc.initialized(petsclib) = true
PETSc.finalized(petsclib) = false
PETSc.finalize(petsclib) = nothing
PETSc.initialized(petsclib) = false
PETSc.finalized(petsclib) = true

libpetsc_double_complex_Int64.dylib
PETSc.initialized(petsclib) = false
PETSc.initialize(petsclib) = nothing
PETSc.initialized(petsclib) = true
PETSc.finalized(petsclib) = false
PETSc.finalize(petsclib) = nothing
PETSc.initialized(petsclib) = false
PETSc.finalized(petsclib) = true

libpetsc_single_complex_Int64.dylib
PETSc.initialized(petsclib) = false
PETSc.initialize(petsclib) = nothing
PETSc.initialized(petsclib) = true
PETSc.finalized(petsclib) = false
PETSc.finalize(petsclib) = nothing
PETSc.initialized(petsclib) = false
PETSc.finalized(petsclib) = true

@jkozdon
Copy link
Copy Markdown
Member Author

jkozdon commented Jul 16, 2021

I guess I still need to sort out the types (But I think it should be possible with more walking of the syntax tree).

@psanan
Copy link
Copy Markdown
Contributor

psanan commented Jul 20, 2021

Lazy question, but what's the high-level procedure here? What is now automatic and what still has to be maintained "by hand"? Are the specific things here related to various PETSc components all of the "by hand" flavor, or are those things that have been generated automatically and are then checked in?

@vchuravy
Copy link
Copy Markdown
Member

I think everything in lib is autogenerated.

@jkozdon
Copy link
Copy Markdown
Member Author

jkozdon commented Jul 20, 2021

As @vchuravy said, the file in lib is generated from the PETSc header files with the code in gen. These produce pretty raw wrappers, that I am then expanding on to make it all a little more friendly to work with.

There is a bunch of stuff we do not currently wrap (look at generator.toml), some of it will need to be sorted out and some of it won't (I think I know / have a plan for how to support most of what will be needed, just waiting to fix it until I am ready to use it / write the test).

There probably some gotchas left in there with respect to system / build dependent types that will need to be sorted out, but right now it does support multiple PETSc builds living side-by-side in Julia.

@psanan shoot me an email if you'd like to VTC to chat about what I am doing, I'd be more than happy to have feedback.

@jkozdon jkozdon force-pushed the jek/gen branch 2 times, most recently from 53fc7ab to aa8e660 Compare July 21, 2021 23:09
@jkozdon jkozdon force-pushed the jek/gen branch 4 times, most recently from afbe26f to 0f22d51 Compare August 3, 2021 19:55
@boriskaus boriskaus marked this pull request as ready for review August 3, 2021 21:49
@jkozdon jkozdon force-pushed the jek/gen branch 4 times, most recently from 3e3e0f9 to 1850ac4 Compare August 4, 2021 17:53
@psanan
Copy link
Copy Markdown
Contributor

psanan commented Aug 5, 2021

Docs suggestion, re our chat our yesterday. Perhaps somewhere like here one could add language like "PETSc.jl's high-level, easy-to-use interface exposes only some of the functionality of PETSc. However, PETSc.jl includes an automatically-generated wrapper layer which directly exposes more of the PETSc API, which may be of use to existing expert users. See (link to minimal example/test of using the wrappers, directly) for an example".

@jkozdon
Copy link
Copy Markdown
Member Author

jkozdon commented Aug 5, 2021

Thanks for the recommendation. I've put it as part of the PR task list.

@boriskaus
Copy link
Copy Markdown
Collaborator

I’m a PETSc user (well at least of part of the library). Yet I’m only a beginner when it comes to using clang to port it all.
I did notice in a recent project that it is possible to automatically make julia docs out of doxygen strings (which every routine in petsc has).
It would be fantastic if we can automatically provide help for all of the routines (even when the help is strictly speaking only valid for the c routines)

If you leave out the functions that have ccalls in the current main, there are only a limited number of additional functions remaining that are mainly there to make using petsc more julia-like. Those ones could be gradually expanded to include more functionally, but as long as we call autowrapped routines throughout it will be much easier to maintain this.

@ViralBShah
Copy link
Copy Markdown
Member

ViralBShah commented Oct 16, 2024

So with your generated library, did you try doing include petsc_library.jl? Getting it to load cleanly is the first step. I assume you used the generator.toml that is in this branch (which has a lot of stuff to exclude and such).

I see what you are saying about the auto-generated comments for the wrappers. Wouldn't we still need the docs that are in the Julian interface as it stands right now - or are you thinking those could be completely replaced with this auto-generated stuff?

@boriskaus
Copy link
Copy Markdown
Collaborator

So with your generated library, did you try doing include petsc_library.jl? Getting it to load cleanly is the first step. I assume you used the generator.toml that is in this branch (which has a lot of stuff to exclude and such).

I didn’t manage to load it just now; I was using a simpler generator.toml shown in one of the comments

I see what you are saying about the auto-generated comments for the wrappers. Wouldn't we still need the docs that are in the Julian interface as it stands right now - or are you thinking those could be completely replaced with this auto-generated stuff?

I think it can be replaced with autogenerated stuff. Multiple dispatch will take care of the rest.

@boriskaus
Copy link
Copy Markdown
Collaborator

boriskaus commented Oct 28, 2024

@ViralBShah, @vchuravy

One of the reasons for the wrapper file to be rather complex is that the different versions of the PETSc libraries have different definitions of PetscInt, PetscScalar, etc. which can be 32bit, 64bit etc.
In the main branch, we handle this by interpolating the values of $PetscInt, $PetscScalar into function calls as can be seen here

Yet, this doesn't work for structures, which are instead defined as:

mutable struct DMSTAGSTENCIL{PetscInt}
    loc::DMStagStencilLocation
    i::PetscInt
    j::PetscInt
    k::PetscInt
    c::PetscInt
end

At the time the initial wrapping was done, it wasn't possible to automatically wrap C structures to give something like above. Instead Clang gives something like:

mutable struct DMStagStencil
    loc::DMStagStencilLocation
    i::PetscInt
    j::PetscInt
    k::PetscInt
    c::PetscInt
    DMStagStencil() = new()
end

Question: do you know whether there is a way to automatically add types to the structures using Clang?
If yes, it would greatly simplify the generator.toml file.

EDIT: @albert-de-montserrat pointed out that this is actually done already in wrap.jl. The disadvantage is that it has to be specified manually for every struct as:

(x, s) -> add_struct_type(x, s, ("MatStencil",), ("PetscInt",)),

@boriskaus
Copy link
Copy Markdown
Collaborator

@ViralBShah it now loads again and some of the tests work. Quite a bit of work remains to automatically wrap the structs (if that is possible at all).

@boriskaus
Copy link
Copy Markdown
Collaborator

boriskaus commented Nov 6, 2024 via email

@ViralBShah
Copy link
Copy Markdown
Member

Perhaps @Gnimuc can chime in, if they have the time to look at this.

This adds an auto-wrapping tool that creates more julia-friendly functions for the PETSc functions created by the Clang.jl.
It is tested on the DMSTAG routines where most of the routines defined in the petscdmstag.h header file are now translated, including their doc strings.
There is still some stuff that needs manual work, but that is mostly indicated by "TODO" comments. Tests are also provided for most routines

Since functions rarely change between different PETSc versions, it is unlikely that much needs to be re-wrapped between different PETSc releases.
I expect that the "wrap_functions.jl" routine will also be helpful in many of the other petsc header files, but have not tested this yet.
@boriskaus
Copy link
Copy Markdown
Collaborator

took a bit of time but I now added a (mostly) automatic wrapper tool that creates Julia-friendly functions of the functions generated by Clang.jl. This includes docstrings and tests, which makes the whole experience of using PETSc from Julia much more pleasant.
This is currently tested for the DMSTAG routines (see dmstag_wrapper.jl).

@ViralBShah
Copy link
Copy Markdown
Member

When I looked at this last, it felt like redoing this on top of master picemeal may be easier than trying to rebase this PR to master (which at least for me felt really complex).

@boriskaus
Copy link
Copy Markdown
Collaborator

When I looked at this last, it felt like redoing this on top of master picemeal may be easier than trying to rebase this PR to master (which at least for me felt really complex).

Not sure I understand what you mean.

I am trying to port the tests from main into this branch bit by bit, so we can ensure that we have at least the same functionality

@ViralBShah
Copy link
Copy Markdown
Member

Ah - I suppose the merge conflicts will then get resolved when all tests are migrated.

@jkozdon
Copy link
Copy Markdown
Member Author

jkozdon commented May 16, 2025

Is this still being worked on or can we close it?

@boriskaus
Copy link
Copy Markdown
Collaborator

I work on it every few months, but was indeed porting things to a new branch (as this one is a bit large by now)

@jkozdon jkozdon closed this Aug 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

6 participants